package com.example.plantuml.tools;

import com.example.plantuml.model.MethodCall;
import com.example.plantuml.model.RequestTrace;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 调用链管理器，使用ThreadLocal存储每个请求的调用链信息
 */
@Service
public class CallChainManager {
    @Value("${server.port:8080}")
    private int serverPort;

    // 存储当前线程的调用栈
    private ThreadLocal<MethodCall> currentMethodCall = new ThreadLocal<>();

    // 存储当前请求的跟踪信息
    private ThreadLocal<RequestTrace> currentRequestTrace = new ThreadLocal<>();

    // 存储所有完成的请求跟踪信息，最多保留N条（可配置）
    private final Map<String, RequestTrace> completedTraces;

    // 最大存储记录数，从配置文件读取，默认10
    private final int maxRecords;
    private final long minDurationMs;  // 新增：最小记录时长阈值(毫秒)

    // 通过构造函数注入配置值
    public CallChainManager(int maxRecords, long minDurationMs) {
        this.maxRecords = maxRecords;
        this.minDurationMs = minDurationMs;

        // 初始化LinkedHashMap实现LRU淘汰策略
        this.completedTraces = new LinkedHashMap<String, RequestTrace>(maxRecords, 0.75f, true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<String, RequestTrace> eldest) {
                // 当记录数超过最大限制时移除最旧记录
                return size() > maxRecords;
            }
        };
    }

    /**
     * 开始新的请求跟踪
     */
    public void startRequestTrace(RequestTrace requestTrace) {
        currentRequestTrace.set(requestTrace);
        currentMethodCall.set(null);
    }

    /**
     * 开始方法调用跟踪
     */
    public MethodCall startMethodCall(ProceedingJoinPoint joinPoint) {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        String parameterDesc = getParameterDescription(joinPoint);

        MethodCall methodCall = new MethodCall();
        methodCall.setClassName(className);
        methodCall.setMethodName(methodName);
        methodCall.setParameterDesc(parameterDesc);
        methodCall.setStartTime(System.currentTimeMillis());
        // 设置父方法
        MethodCall parent = currentMethodCall.get();
        if (parent != null) {
            methodCall.setParentId(parent.getId());
            parent.getChildren().add(methodCall);
        } else {
            // 如果没有父方法，说明是根方法(Controller方法)
            RequestTrace requestTrace = currentRequestTrace.get();
            if (requestTrace != null) {
                requestTrace.setRootMethod(methodCall);
            }
        }

        // 更新当前方法为新方法
        currentMethodCall.set(methodCall);

        return methodCall;
    }

    /**
     * 结束方法调用跟踪
     */
    public void endMethodCall() {
        MethodCall methodCall = currentMethodCall.get();
        if (methodCall != null) {
            methodCall.setEndTime(System.currentTimeMillis());
            methodCall.calculateDuration();

            // 恢复到父方法
            RequestTrace requestTrace = currentRequestTrace.get();
            if (requestTrace != null && requestTrace.getRootMethod() != null &&
                    requestTrace.getRootMethod().getId().equals(methodCall.getId())) {
                // 如果是根方法，恢复为null
                currentMethodCall.set(null);
            } else {
                // 查找父方法
                currentMethodCall.set(findParentMethodCall(requestTrace.getRootMethod(), methodCall.getParentId()));
            }
        }
    }

    /**
     * 结束请求跟踪
     */
    public RequestTrace endRequestTrace() {
        RequestTrace requestTrace = currentRequestTrace.get();
        if (requestTrace != null) {
            requestTrace.setEndTime(System.currentTimeMillis());
            requestTrace.calculateTotalDuration();
            if (requestTrace.getTotalDuration() >= minDurationMs) {
                completedTraces.put(requestTrace.getTraceId(), requestTrace);
            }
        }

        // 清除线程本地变量
        currentRequestTrace.remove();
        currentMethodCall.remove();

        return requestTrace;
    }

    /**
     * 根据ID查找父方法调用
     */
    private MethodCall findParentMethodCall(MethodCall methodCall, String parentId) {
        if (methodCall == null || parentId == null) {
            return null;
        }

        if (methodCall.getId().equals(parentId)) {
            return methodCall;
        }

        for (MethodCall child : methodCall.getChildren()) {
            MethodCall found = findParentMethodCall(child, parentId);
            if (found != null) {
                return found;
            }
        }

        return null;
    }

    /**
     * 获取已完成的请求跟踪
     */
    public RequestTrace getCompletedTrace(String traceId) {
        return completedTraces.get(traceId);
    }

    /**
     * 获取所有已完成的请求跟踪ID
     */
    public Map<String, String> getAllTraceIds() {
        Map<String, String> result = new HashMap<>();
        completedTraces.forEach((traceId, trace) -> {
//            result.put(traceId, trace.getHttpMethod() + " " + trace.getRequestUrl() +
//                    " (" + trace.getTotalDuration() + "ms)");
            result.put(traceId, "http://127.0.0.1:" + serverPort + "/traces/plantuml/" + traceId);
        });
        return result;
    }

    // 新增：获取当前配置的最大记录数
    public int getMaxRecords() {
        return maxRecords;
    }


    /**
     * 获取方法参数描述
     */
    protected String getParameterDescription(ProceedingJoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return "()";
        }

        StringBuilder params = new StringBuilder("(");
        for (int i = 0; i < args.length; i++) {
            if (i > 0) {
                params.append(", ");
            }
            if (args[i] != null) {
                params.append(args[i].getClass().getSimpleName());
            } else {
                params.append("null");
            }
        }
        params.append(")");

        return params.toString();
    }
}